package admin

import (
	"encoding/json"
	"github.com/go-playground/validator/v10"
	"github.com/zeebo/errs"
	"go.uber.org/zap"
	"io"
	"net/http"
	"unsafe"
)

// Error is default error class for admin package.
var Error = errs.Class("Admin")

func bind(r *http.Request, res any) error {
	body, err := io.ReadAll(r.Body)
	if err != nil {
		return err
	}
	err = json.Unmarshal(body, &res)
	if err != nil {
		return err
	}
	return validator.New().Struct(res)
}

func (server *Server) sendJSONError(w http.ResponseWriter, errMsg, detail string, statusCode int) {
	errStr := struct {
		Error  string `json:"error"`
		Detail string `json:"detail"`
	}{
		Error:  errMsg,
		Detail: detail,
	}
	server.sendJSONData(w, statusCode, errStr)
}

func (server *Server) sendJSONData(w http.ResponseWriter, statusCode int, data any) {
	var msg []byte
	var err error
	switch data.(type) {
	case string:
		msg = []byte(*((*string)(unsafe.Pointer(&data))))
		break
	case []byte:
		msg = *((*[]byte)(unsafe.Pointer(&data)))
		break
	default:
		msg, err = json.Marshal(data)
		if err != nil {
			server.sendJSONError(w, "json encoding failed",
				err.Error(), http.StatusInternalServerError)
			return
		}
	}

	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(statusCode)
	_, err = w.Write(msg) // any error here entitles a client side disconnect or similar, which we do not care about.
	server.log.Debug("sendJSONData", zap.ByteString("response", msg), zap.Int("code", statusCode))
}
